<template>
  <div class="canvas-container" @mousedown="startDrag" ref="containerRef" @wheel="wheelEvent">
    <div class="target-container" :style="style" @click.self="selectStage">
      <draggable-resizable-vue
        v-for="item in data"
        :key="item.id"
        v-model:x="item.x"
        v-model:y="item.y"
        v-model:h="item.h"
        v-model:w="item.w"
        :class="[{ active: item.id === current?.id }]"
        parent=".target-container"
        :z="item.z"
        :resizable="false"
        :scale="props.scale"
        :draggable="edit"
        @click="selectItem(item)"
        class="drag-item"
      >
        <XImage :preview="false" :src="item.imageSrc" class="w-full h-full" />
      </draggable-resizable-vue>
      <!-- 宽高 -->
      <div class="line-w">
        <div>{{ width }}px</div>
      </div>
      <div class="line-h">
        <div>{{ height }}px</div>
      </div>
    </div>
  </div>
</template>

<script setup lang="ts">
import type { ThemeCanvas } from '@/types/theme';
import DraggableResizableVue from 'draggable-resizable-vue3';
import type { CSSProperties } from 'vue';

const emit = defineEmits(['select', 'update:scale', 'click-stage']);
const containerRef = ref<HTMLElement | null>();
const stage = ref({
  x: 0,
  y: 0,
});

const current = defineModel<ThemeCanvas>('modelValue');
onMounted(() => {
  if (!containerRef.value) return;
  const { width, height } = containerRef.value.getBoundingClientRect();
  stage.value.x = (width - props.width) / 2;
  stage.value.y = (height - props.height) / 2;
});
const props = withDefaults(
  defineProps<{
    data: ThemeCanvas[];
    width: number;
    height: number;
    background: string;
    edit?: boolean;
    scale: number;
  }>(),
  {
    scale: 1,
  },
);
const startDrag = (de: MouseEvent) => {
  let startX = de.x;
  let startY = de.y;
  const target = de.target as HTMLElement;
  if (!target.classList.contains('canvas-container')) return;
  const mousemove = (me: MouseEvent) => {
    const offsetX = me.x - startX;
    const offsetY = me.y - startY;

    stage.value.x += offsetX;
    stage.value.y += offsetY;
    startX = me.x;
    startY = me.y;
  };
  const mouseup = () => {
    document.removeEventListener('mousemove', mousemove);
    document.removeEventListener('mouseup', mouseup);
  };
  document.addEventListener('mousemove', mousemove);
  document.addEventListener('mouseup', mouseup);
};

const selectItem = (item: ThemeCanvas) => {
  emit('select', item);
};
const selectStage = () => {
  emit('click-stage');
};

const wheelEvent = (e: WheelEvent) => {
  e.preventDefault();
  const delta = e.deltaY > 0 ? 0.1 : -0.1;

  const scaleDelta = Number(Math.min(Math.max(props.scale + delta, 0.2), 2).toFixed(1));
  emit('update:scale', scaleDelta);
};

const style = computed((): CSSProperties => {
  const background = props.background ? `url(${props.background})` : 'white';
  return {
    width: `${props.width}px`,
    height: `${props.height}px`,
    background,
    transform: `scale(${props.scale}) translate(${stage.value.x / props.scale}px, ${stage.value.y / props.scale}px)`,
    border: '1px solid #ddd',
  };
});
</script>

<style lang="scss" scoped>
.canvas-container {
  border: 1px solid var(--border-color);
  background-color: var(--background-color);
  background-size: cover;
  background-position: center;
  overflow: hidden;
  border-radius: var(--radius);
  width: 100%;
  height: 100%;
  .target-container {
    height: 100%;
    width: 100%;
    position: relative;
    background-repeat: no-repeat !important;
    background-size: cover;
    background-position: center;
  }
}
.active {
  border: 2px solid var(--primary) !important;
}
.drv {
  border: 2px dashed transparent;
}
.line-h {
  position: absolute;
  height: 100%;
  right: -24px;
  top: 0;
  z-index: 10;
  writing-mode: vertical-rl;
  text-orientation: upright;
  text-align: center;
}
.line-w {
  position: absolute;
  width: 100%;
  left: 0;
  top: calc(100%);
  z-index: 10;
  text-align: center;
}
.drag-item {
  &:hover {
    filter: brightness(90%) !important;
  }
}
</style>
